package cn.iocoder.yudao.module.asasc.service.salesreport;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
import cn.iocoder.yudao.module.asasc.common.AppUtils;
import cn.iocoder.yudao.module.asasc.config.AsaConst;
import cn.iocoder.yudao.module.asasc.controller.admin.salesreport.vo.SalesReportPageReqVO;
import cn.iocoder.yudao.module.asasc.controller.admin.salesreport.vo.SalesReportSaveReqVO;
import cn.iocoder.yudao.module.asasc.dal.dataobject.salesreport.SalesReportDO;
import cn.iocoder.yudao.module.asasc.dal.mysql.selesreport.SalesReportMapper;
import cn.iocoder.yudao.module.asasc.enums.DictTypeConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.asasc.enums.ErrorCodeConstants.ASC_SALES_REPORT_NOT_EXISTS;

/**
 * ASA管理系统 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
@Slf4j
public class SalesReportServiceImpl implements SalesReportService {

    @Resource
    private SalesReportMapper salesReportMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Integer createSalesReport(SalesReportSaveReqVO createReqVO) {
        // 插入
        SalesReportDO sr = BeanUtils.toBean(createReqVO, SalesReportDO.class);
        String salt = sr.getCustomerCurrency();
        sr.setHash(AppUtils.generateHashWithSalt(sr, salt));

        //汇率转化
        Map<Object, Object> rateMap = stringRedisTemplate.opsForHash().entries(AsaConst.rateKey);
        BigDecimal rate = rateMap.containsKey(sr.getCurrencyOfProceeds()) ?
                new BigDecimal(rateMap.get(sr.getCurrencyOfProceeds()).toString()) : BigDecimal.ONE;

        if (sr.getUnits() < 0) {
            //退款的四个字段都显示成负数
            sr.setDeveloperProceedsUsd(sr.getDeveloperProceeds().divide(rate, 2, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(sr.getUnits())));
            sr.setCustomerPriceUsd(sr.getCustomerPrice().divide(rate, 2, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(sr.getUnits())).negate());
            sr.setCustomerPrice(sr.getCustomerPrice().negate());
        } else {
            sr.setDeveloperProceedsUsd(sr.getDeveloperProceeds().divide(rate, 2, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(sr.getUnits())));
            sr.setCustomerPriceUsd(sr.getCustomerPrice().divide(rate, 2, RoundingMode.HALF_UP)
                    .multiply(BigDecimal.valueOf(sr.getUnits())));
        }

        salesReportMapper.insert(sr);
        // 返回
        return sr.getId();
    }

    @Override
    public void updateSalesReport(SalesReportSaveReqVO updateReqVO) {
        // 校验存在
        validateSalesReportExists(updateReqVO.getId());
        // 更新
        SalesReportDO updateObj = BeanUtils.toBean(updateReqVO, SalesReportDO.class);
        salesReportMapper.updateById(updateObj);
    }

    @Override
    public void deleteSalesReport(Integer id) {
        // 校验存在
        validateSalesReportExists(id);
        // 删除
        salesReportMapper.deleteById(id);
    }

    private void validateSalesReportExists(Integer id) {
        if (salesReportMapper.selectById(id) == null) {
            throw exception(ASC_SALES_REPORT_NOT_EXISTS);
        }
    }

    @Override
    public SalesReportDO getSalesReport(Integer id) {
        return salesReportMapper.selectById(id);
    }

    @Override
    public PageResult<SalesReportDO> getSalesReportPage(SalesReportPageReqVO pageReqVO) {
        return salesReportMapper.selectPage(pageReqVO);
    }

    @Override
    public Map<String, Object> postSalesReport(List<SalesReportSaveReqVO> reqVOS) {
        Map<String, Object> result = new HashMap<>();

        // 把 reqVOS 中的 parentIdentifier 替换成 appleIdentifier
        reqVOS.forEach(a -> {
            if (!a.getParentIdentifier().trim().isBlank()) {
                a.setAppleIdentifier(DictFrameworkUtils.parseDictDataValue(DictTypeConstants.PKG_ID_APP_ID,
                        a.getParentIdentifier()));
            }
        });

        SalesReportSaveReqVO reqVO = new SalesReportSaveReqVO();
        int skippedCount = 0;
        int successCount = 0;

        try {
            for (SalesReportSaveReqVO vo : reqVOS) {
                reqVO = vo;

                try {
                    String orgIdLabel = DictFrameworkUtils.getDictDataLabel(DictTypeConstants.ASA_ORG_APP_ID,
                            vo.getAppleIdentifier());
                    if (!Objects.isNull(orgIdLabel)) {
                        Long orgId = Long.parseLong(orgIdLabel.replace(",", ""));
                        vo.setOrgId(orgId);
                    }
                } catch (Exception ignore) {
                }

                try {
                    createSalesReport(vo);
                    successCount++; // 成功插入计数
                } catch (Exception e) {
                    if (!Objects.isNull(e.getMessage()) && e.getMessage().contains("unique_hash")) {
                        log.warn("Skipping duplicate record: {}", vo);
                        skippedCount++; // 跳过计数
                    } else {
                        log.error("postSalesReport error: {}", e.getMessage());
                    }
                }
            }
            // 返回具体条数
            result.put("success", true);
            result.put("message", String.format("%s 数据上报成功", reqVO.getBeginDate()));
            result.put("salesReport", reqVOS.size());
            result.put("skippedCount", skippedCount);
            result.put("successCount", successCount);
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", e.getMessage());
            result.put("salesReport", reqVOS.size());
            result.put("skippedCount", skippedCount);
            result.put("successCount", successCount);
            e.printStackTrace();
        }

        return result;
    }

}